package com.hnu.service.impl;

import java.util.ArrayList;
import java.util.List;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;

import com.hnu.model.Bookmark;
import com.hnu.model.BookmarkDAO;
import com.hnu.model.Bookmarkbackup;
import com.hnu.model.BookmarkbackupDAO;
import com.hnu.model.Bookmarkpreference;
import com.hnu.model.BookmarkpreferenceDAO;
import com.hnu.model.BookmarksimilarityDAO;
import com.hnu.model.User;
import com.hnu.model.UserDAO;
import com.hnu.model.Userbookmark;
import com.hnu.model.UserbookmarkDAO;
import com.hnu.service.BookmarkServ;
import com.hnu.service.recommender.BookmarkBasedRecommender;
import com.hnu.service.recommender.BookmarkSlopeOneRecommender;
import com.hnu.service.recommender.UserBasedRecommender;
import com.hnu.service.search.LuceneUtil;
import com.hnu.util.PageInfoBean;

public class BookmarkServImpl implements BookmarkServ {
	/**
	 * 用户喜好的最大值
	 */
	private final static int maxPreference = 20;

	/**
	 * 进行索引的界限
	 */
	private final static int uniteSize = 2;

	/**
	 * 每次索引的记录个数
	 */
	private final static int fetchSize = 100;
	private UserDAO userDAO;
	private BookmarkDAO bookmarkDAO;
	private BookmarksimilarityDAO bookmarksimilarityDAO;
	private UserbookmarkDAO userbookmarkDAO;
	private BookmarkpreferenceDAO bookmarkpreferenceDAO;
	private BookmarkbackupDAO bookmarkbackupDAO;

	public boolean addBookmark(long userId, Bookmark bookmark, String indexPath) {
		
		String url = bookmark.getBookmarkUrl();
		if(url.startsWith("http://"))
		{
			url = url.substring(7);
			bookmark.setBookmarkUrl(url);
		}
		
		Userbookmark userbookmark = new Userbookmark();
		userbookmark.setBookmarkDesc(bookmark.getBookmarkDesc());
		userbookmark.setBookmarkTitle(bookmark.getBookmarkTitle());
		userbookmark.setBookmarkUrl(bookmark.getBookmarkUrl());
		
		User user = this.userDAO.findById(userId);
		userbookmark.setUser(user);

		// 下面记录模块要使用
		long bookmarkid;

		List<Bookmark> tempList = new ArrayList<Bookmark>();
		tempList.addAll(this.bookmarkDAO.findByProperty("bookmarkUrl",
				bookmark.getBookmarkUrl()));
		if (tempList.isEmpty()) {
			// 不存在
			
			//设置时间
			bookmark.setEnterTime(System.currentTimeMillis());
			
			this.bookmarkDAO.save(bookmark);
			userbookmark.setBookmark(bookmark);

			bookmarkid = bookmark.getBookmarkId();

			/*
			 * // 进行索引 LuceneUtil.indexBookmark(bookmark, indexPath);
			 */

			// 保存备份已供索引
			Bookmarkbackup bookmarkbackup = new Bookmarkbackup();
			bookmarkbackup.setBackupId(bookmark.getBookmarkId());
			bookmarkbackup.setBookmarkDesc(bookmark.getBookmarkDesc());
			bookmarkbackup.setBookmarkTitle(bookmark.getBookmarkTitle());
			bookmarkbackup.setBookmarkUrl(bookmark.getBookmarkUrl());
			this.bookmarkbackupDAO.save(bookmarkbackup);

		} else {
			// 该书签已存在
			bookmarkid = tempList.get(0).getBookmarkId();
			
			//用户已添加该书签
			if(this.userbookmarkDAO.getUserBookmarkCountByTwo(userId, bookmarkid) > 0)
			{
				return false;
			}
			//用户未添加该书签
			userbookmark.setBookmark(tempList.get(0));
		}
		this.userbookmarkDAO.save(userbookmark);

		// 记录用户喜好
		this.recordBookmark(bookmarkid, userId, 1);
		return true;
	}

	public boolean indexBookmarkBackup(String indexPath) {
		int count = this.bookmarkbackupDAO.getBookmarkbackupTotalCount();
		List<Bookmarkbackup> backupList = null;
		Bookmark bookmark = null;

		while (count >= this.uniteSize) {
			backupList = this.bookmarkbackupDAO
					.getOneUnitBookmarkbackup(this.fetchSize);
			if (backupList != null) {
				for (Bookmarkbackup backup : backupList) {
					bookmark = new Bookmark();
					bookmark.setBookmarkId(backup.getBackupId());
					bookmark.setBookmarkDesc(backup.getBookmarkDesc());
					bookmark.setBookmarkTitle(backup.getBookmarkTitle());
					bookmark.setBookmarkUrl(backup.getBookmarkUrl());
					// 进行索引
					LuceneUtil.indexBookmark(bookmark, indexPath);
				}
				this.bookmarkbackupDAO.deleteBookmarkbackup(backupList);
				count = this.bookmarkbackupDAO.getBookmarkbackupTotalCount();
			}
		}
		return true;

	}

	public boolean collectBookmark(long bookmarkId, long userId) {
		int count = this.userbookmarkDAO.getUserBookmarkCountByTwo(userId,
				bookmarkId);
		if (count < 1) {
			Bookmark bookmark = this.bookmarkDAO.findById(bookmarkId);
			User user = this.userDAO.findById(userId);

			Userbookmark userbookmark = new Userbookmark();
			userbookmark.setUser(user);
			userbookmark.setBookmark(bookmark);
			userbookmark.setBookmarkDesc(bookmark.getBookmarkDesc());
			userbookmark.setBookmarkTitle(bookmark.getBookmarkTitle());
			userbookmark.setBookmarkUrl(bookmark.getBookmarkUrl());
			this.userbookmarkDAO.save(userbookmark);

			// 记录用户喜好
			this.recordBookmark(bookmarkId, userId, 1);
			return true;
		} else {
			return false;
		}
	}

	public boolean updateUserBookmark(Userbookmark userbookmark) {
		this.userbookmarkDAO.merge(userbookmark);
		return true;
	}

	public boolean deleteUserBookmark(long userBookmarkId) {
		Userbookmark userbookmark = this.userbookmarkDAO
				.findById(userBookmarkId);
		this.userbookmarkDAO.delete(userbookmark);
		return true;
	}

	public Userbookmark getUserBookmarkByID(long userBookmarkId) {
		Userbookmark userbookmark = this.userbookmarkDAO
				.findById(userBookmarkId);
		return userbookmark;
	}

	public int getUserBookmarkCountByUserId(long userId) {
		return this.userbookmarkDAO.getUserBookmarkCountByUserId(userId);
	}

	public PageInfoBean getUserBookmarkByUserId(long userId, int pageSize,
			int pageIndex) {
		return this.userbookmarkDAO.getUserBookmarkByUserId(userId, pageSize,
				pageIndex);
	}

	public String recordBookmark(long bookmarkId, long userId, int choice) {
		// 权重
		int weight = 1;
		if (choice == 1) {
			weight = 5;
		}

		// 判断是否已有值
		List<Bookmarkpreference> tempList = new ArrayList<Bookmarkpreference>();
		tempList.addAll(this.bookmarkpreferenceDAO.getBookmarkpreferenceByTwo(
				userId, bookmarkId));
		int count = tempList.size();

		Bookmark bookmark = this.bookmarkDAO.findById(bookmarkId);

		Bookmarkpreference bookmarkpreference;
		if (count < 1) {
			bookmarkpreference = new Bookmarkpreference();

			User user = this.userDAO.findById(userId);
			bookmarkpreference.setUser(user);

			bookmarkpreference.setBookmark(bookmark);

			bookmarkpreference.setPreference(weight);

			this.bookmarkpreferenceDAO.save(bookmarkpreference);
		} else {
			bookmarkpreference = tempList.get(0);
			int preference = bookmarkpreference.getPreference().intValue();
			preference = preference + weight;
			if (preference > this.maxPreference) {
				preference = this.maxPreference;
			}
			bookmarkpreference.setPreference(preference);

			this.bookmarkpreferenceDAO.merge(bookmarkpreference);
		}

		return bookmark.getBookmarkUrl();
	}

	public List<Bookmark> getTopNContentSimilar(long bookmarkId, int count,
			String indexPath) {
		Bookmark bookmark = this.bookmarkDAO.findById(bookmarkId);
		return LuceneUtil.searchBookmark(bookmark.getBookmarkTitle(),
				indexPath, count);
	}
	
	public List<Bookmark> getTopNBookmark(int count)
	{
		return this.bookmarkpreferenceDAO.getTopNBookmark(count, System.currentTimeMillis());
	}

	public List<Bookmark> getUserBasedRecommendBookmark(long userID, int howmany) {
		List<Bookmark> bookmarkList = new ArrayList<Bookmark>();
		try {
			// 基于用户相似度的推荐
			UserBasedRecommender userRecommender = new UserBasedRecommender();
			List<RecommendedItem> itemList = userRecommender.recommend(userID,
					howmany);
			Bookmark bookmark;
			for (RecommendedItem item : itemList) {
				bookmark = this.bookmarkDAO.findById(item.getItemID());
				bookmarkList.add(bookmark);
			}

			// 基于Slope one的推荐
			BookmarkSlopeOneRecommender slopeOneRecommender = new BookmarkSlopeOneRecommender();
			itemList = slopeOneRecommender.recommend(userID, howmany);
			boolean canAdd = true;
			for (RecommendedItem item : itemList) {
				for (Bookmark tempBookmark : bookmarkList) {
					if (tempBookmark.getBookmarkId() == item.getItemID()) {
						canAdd = false;
						break;
					}
				}
				if (canAdd) {
					bookmark = this.bookmarkDAO.findById(item.getItemID());
					bookmarkList.add(bookmark);
				}
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(bookmarkList.isEmpty())
		{
			bookmarkList.addAll(this.getTopNBookmark(10));
		}
		
		return bookmarkList;
	}

	public List<Bookmark> getBookmarkBasedRecommendBookmark(long bookmarkID,
			int howmany) {
		List<Bookmark> bookmarkList = new ArrayList<Bookmark>();
		try {
			BookmarkBasedRecommender recommender = new BookmarkBasedRecommender();
			List<RecommendedItem> itemList = recommender.recommend(bookmarkID,
					howmany);
			Bookmark bookmark;
			for (RecommendedItem item : itemList) {
				bookmark = this.bookmarkDAO.findById(item.getItemID());
				bookmarkList.add(bookmark);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bookmarkList;
	}

	public List<Bookmark> getSearchBookmark(String query, int howmany,
			String indexPath) {

		return LuceneUtil.searchBookmark(query, indexPath, howmany);
	}

	public String dispatchBookmark(long bookmarkId) {
		Bookmark bookmark = this.bookmarkDAO.findById(bookmarkId);
		return bookmark.getBookmarkUrl();
	}

	public UserDAO getUserDAO() {
		return userDAO;
	}

	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}

	public BookmarkDAO getBookmarkDAO() {
		return bookmarkDAO;
	}

	public void setBookmarkDAO(BookmarkDAO bookmarkDAO) {
		this.bookmarkDAO = bookmarkDAO;
	}

	public BookmarksimilarityDAO getBookmarksimilarityDAO() {
		return bookmarksimilarityDAO;
	}

	public void setBookmarksimilarityDAO(
			BookmarksimilarityDAO bookmarksimilarityDAO) {
		this.bookmarksimilarityDAO = bookmarksimilarityDAO;
	}

	public UserbookmarkDAO getUserbookmarkDAO() {
		return userbookmarkDAO;
	}

	public void setUserbookmarkDAO(UserbookmarkDAO userbookmarkDAO) {
		this.userbookmarkDAO = userbookmarkDAO;
	}

	public BookmarkpreferenceDAO getBookmarkpreferenceDAO() {
		return bookmarkpreferenceDAO;
	}

	public void setBookmarkpreferenceDAO(
			BookmarkpreferenceDAO bookmarkpreferenceDAO) {
		this.bookmarkpreferenceDAO = bookmarkpreferenceDAO;
	}

	public void setBookmarkbackupDAO(BookmarkbackupDAO bookmarkbackupDAO) {
		this.bookmarkbackupDAO = bookmarkbackupDAO;
	}

	public BookmarkbackupDAO getBookmarkbackupDAO() {
		return bookmarkbackupDAO;
	}

	public boolean isCanModify(long userbookmarkID, long userID) {
		
		return this.userbookmarkDAO.isCanModify(userbookmarkID, userID);
	}

}
